package org.pub.lunch.mashup.google;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.NameValuePair;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.pub.lunch.mashup.google.js.JSArray;
import org.pub.lunch.mashup.google.js.JSObject;
import org.pub.lunch.mashup.google.js.JSUTF8;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.util.Log;

/**
 * @author Kyungseop Kim
 * 
 */

public class LocalAgent {

	private static final String TAG = LocalAgent.class.toString();
	private static final String PROTO = "http";
	private static final String HOST = "maps.google.co.kr";
	public static final int RESTAURANT_LIMIT = 30;
	private DefaultHttpClient client;
	private HttpGet _request;
	private Location location;
	private int start;
	private Context context;

	public Location getLocation() {
		return location;
	}

	public void setLocation(Location location) {
		this.location = location;
	}

	public LocalAgent() {
		super();
		// TODO Auto-generated constructor stub
		client = new DefaultHttpClient();

		_request = new HttpGet();
		_request.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		_request.setHeader("Accept-Language", "en-us,en;q=0.5");
		_request.setHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
		start = 0;
	}

	public LocalAgent(Context context, Location loc) throws Exception {
		this();
		this.location = loc;
		this.context = context;
	}

	protected List<NameValuePair> getParams(Location location) throws Exception {

		List<NameValuePair> qparams = new ArrayList<NameValuePair>();

		StringBuffer current = new StringBuffer();

		current.append(location.getLatitude());
		current.append(",");
		current.append(location.getLongitude());

		Geocoder coder = new Geocoder(context);

		List<Address> address = coder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

		qparams.add(new BasicNameValuePair("near", address.get(0).getAddressLine(0)));
		qparams.add(new BasicNameValuePair("q", "\uC74C\uC2DD\uC810"));
		qparams.add(new BasicNameValuePair("output", "js"));
		qparams.add(new BasicNameValuePair("ssl", current.toString()));
		qparams.add(new BasicNameValuePair("sspn", "0.00778,0.01929"));
		qparams.add(new BasicNameValuePair("jsv", "209c"));
		qparams.add(new BasicNameValuePair("f", "li"));
		qparams.add(new BasicNameValuePair("vps", "2"));
		qparams.add(new BasicNameValuePair("\uAC80\uC0C9", "\uAC80\uC0C9"));
		qparams.add(new BasicNameValuePair("radius", "1.242742"));
		return qparams;
	}

	public URI takeUri(Location loc) throws Exception {

		return takeUri(getParams(loc));
	}

	public URI takeUri(List<NameValuePair> params) throws Exception {

		URI uri = URIUtils.createURI(PROTO, HOST, -1, "/maps", URLEncodedUtils.format(params, "UTF-8"), null);

		return uri;
	}

	public String request(int begin) throws Exception {

		ResponseHandler<String> h = new BasicResponseHandler();

		if (begin == 0) {
			_request.setURI(takeUri(location));
		} else {
			List<NameValuePair> params = getParams(location);
			params.add(new BasicNameValuePair("start", String.valueOf(begin)));
			_request.setURI(takeUri(params));
		}
		Log.i("REQUEST", _request.getURI().toString());
		return client.execute(_request, h);

	}

	protected String extractJSO(String html) {
		Matcher mat = Pattern.compile("loadVPage\\((.+),\"state\"\\);\\}//]]>").matcher(html);
		return (mat.find()) ? mat.group(1) : html;
	}

	public List<URI> getLoadUrl(String src) throws Exception {
		Matcher m = Pattern.compile("loadUrl\\('(.*?)',").matcher(src);

		ArrayList<URI> ret = new ArrayList<URI>();
		while (m.find()) {
			ret.add(URIUtils.createURI(PROTO, HOST, 0, JSUTF8.convertJSUTF8(m.group(1)), null, null));
		}
		return ret;
	}

	public List<Restaurant> takeRestaurants(String html) throws Exception {

		String jsstring = extractJSO(html);
		Log.i("GET JS", jsstring);

		JSObject obj = new JSObject(jsstring);

		if (obj.hasKey("overlays")) {
			JSObject olay = obj.getObject("overlays");

			if (olay.hasKey("markers")) {
				JSArray markers = olay.getArray("markers");
				List<Restaurant> restaurants = new ArrayList<Restaurant>();
				Log.i("markers", String.valueOf(markers.length()));
				for (String objstr : markers.items()) {

					Log.i("tag", objstr);
					if (objstr.indexOf("phones") != -1) {
						restaurants.add(new Restaurant(new JSObject(objstr)));
					}
				}
				return restaurants;
			}
		}

		return null;
	}

	public List<Restaurant> getRestaurants() throws Exception {
		// TODO Auto-generated method stu
		List<Restaurant> ret = new ArrayList<Restaurant>();

		List<Restaurant> result;
		setStart(0);
		while (ret.size() < RESTAURANT_LIMIT && (result = getStepByStep()) != null)
			ret.addAll(result);

		return ret;
	}

	public List<Restaurant> getStepByStep() throws Exception {
		String response;
		if ((response = request(start)) == null)
			return null;
		start += 10;
		return takeRestaurants(response);
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}

}
